package com.compute.serviceImpl;

import com.compute.bean.FixedEvent;
import com.compute.bean.Task;
import com.compute.service.EventManageService;
import com.compute.serviceImpl.ManageAlgorithm.TaskManageAlgorithm;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;

import static Tools.DateCompute.getNowMinutesByWeekNumAndMinutes;
import static Tools.DateCompute.getNowMinutesFrom20200106;

/**
 * 活动安排的计算部分
 * @author 李天航
 */
@Service
public class EventManageServiceImpl implements EventManageService {

    @Resource
    TaskManageAlgorithm manageAlgorithm;
    @Resource
    LinkedHashMap<String, Method> algorithmMap;

    @AllArgsConstructor
    public static class TaskAndVis{
        Task task;
        boolean vis;
    }

    /**
     * 尝试安排活动
     * @param alreadyIn 已经安排好的活动
     * @param tasks 待安排的活动
     * @param idx 当前在安排第几个活动
     * @param insertidx 上一次安排的活动的下标
     * @return 是否成功
     */
    private boolean trySearchAnswer(List<FixedEvent> alreadyIn, List<TaskAndVis> tasks, int idx, int insertidx)
    {
        if(idx==tasks.size()||tasks.size()==0)
        {
            return true;
        }
        long weekNum=tasks.get(0).task.getWeekNum();
        for(TaskAndVis taskAndVis:tasks)
        {
            if(!taskAndVis.vis)
            {
                int j=insertidx;
                while(j+1<alreadyIn.size()
                        &&(alreadyIn.get(j+1).getBeginTime()-alreadyIn.get(j).getEndTime())<taskAndVis.task.getTaskTime()
                        &&getNowMinutesByWeekNumAndMinutes(weekNum,alreadyIn.get(j).getEndTime())<getNowMinutesFrom20200106()
                ) {
                    j++;
                }
                long beginTime=alreadyIn.get(j).getEndTime();
                long endTime=beginTime+taskAndVis.task.getTaskTime();
                //结束时间超过底线
                if(endTime>=taskAndVis.task.getTaskDeadline())
                {
                    continue;
                }
                alreadyIn.add(j+1,new FixedEvent(taskAndVis.task,alreadyIn.get(j).getEndTime()));
                taskAndVis.vis=true;
                if(trySearchAnswer(alreadyIn,tasks,idx+1,j)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 活动安排算法
     * @param alreadyIn 固定活动列表
     * @param tasks     任务列表
     * @param algorithmName
     * @return status, msg
     */
    @Override
    public LinkedHashMap<String, Object> eventManage(List<FixedEvent> alreadyIn, List<Task> tasks, String algorithmName) {
        LinkedHashMap<String, Object> resultMap=new LinkedHashMap<>();
        //判断是否有冲突的活动
        for(int i=1;i<alreadyIn.size();i++) {
            if(alreadyIn.get(i).getBeginTime()<alreadyIn.get(i-1).getEndTime()) {
                resultMap.put("status",500);
                resultMap.put("msg","活动冲突");
                resultMap.put("fixedEvent1",alreadyIn.get(i));
                resultMap.put("fixedEvent2",alreadyIn.get(i-1));
                return resultMap;
            }
        }

        if(invokeAlgorithmByName(algorithmName,alreadyIn,tasks)) {
            resultMap.put("status",200);
            resultMap.put("msg","安排成功");
            resultMap.put("results",alreadyIn);
        } else {
            resultMap.put("status",500);
            resultMap.put("msg","时间紧张无法安排");
        }
        return resultMap;
    }

    @SneakyThrows
    @Override
    public boolean invokeAlgorithmByName(String algorithmName, List<FixedEvent> events, List<Task> tasks) {
        Method method = algorithmMap.get(algorithmName);
        try {
            Object results = method.invoke(manageAlgorithm, events, tasks);
            events.clear();
            events.addAll((List<FixedEvent>) results);
        } catch (Exception e){
            return false;
        }
        return true;
    }

}
